home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
476-500
/
500
/
wiconify
/
wiconify-source.lzh
/
Source
/
wLists.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-04-19
|
13KB
|
539 lines
/*
* WICONIFY A utility that allows you to iconify any Intuition window
* on any screen, and to open WB windows on any screen.
*
* wLists.c Handles screen, window, and icon lists.
*
* Copyright 1990 by Davide P. Cervone, all rights reserved.
* You may use this code, provided this copyright notice is kept intact.
*/
#include "wHandler.h"
#include <libraries/dos.h>
#define INTUIMESSAGE ((struct IntuiMessage *)theMessage)
/*
* FindScreen()
*
* Start with the first screen
* While there are more screens and this one is not the one we want
* Go on to the next screen
* Return the scren found or NULL
*/
WSCREEN *FindScreen(theScreen)
struct Screen *theScreen;
{
WSCREEN *ChkScreen;
Forbid();
ChkScreen = FirstScreen;
while (ChkScreen && ChkScreen->Screen != theScreen)
ChkScreen = ChkScreen->Next;
Permit();
return(ChkScreen);
}
/*
* LinkScreen()
*
* Link the screen structure into the link list of screens
*/
void LinkScreen(theScreen)
WSCREEN *theScreen;
{
Forbid();
theScreen->Next = FirstScreen; theScreen->Prev = NULL;
if (FirstScreen) FirstScreen->Prev = theScreen;
FirstScreen = theScreen;
Permit();
}
/*
* UnLinkScreen()
*
* Unlink the screen from the linked list
* If it is marked for refreshing, remove it from that linked list, too
*/
void UnLinkScreen(theScreen)
WSCREEN *theScreen;
{
Forbid();
if (theScreen->Flags & WI_REFRESH) UnLinkRefresh(theScreen);
if (theScreen->Next) theScreen->Next->Prev = theScreen->Prev;
if (theScreen->Prev) theScreen->Prev->Next = theScreen->Next;
else FirstScreen = theScreen->Next;
Permit();
}
/*
* NewWBScreen()
*
* Make the specified screen the new WB screen
*/
void NewWBScreen(theScreen)
WSCREEN *theScreen;
{
Forbid();
if (theScreen == RealWB) WBScreen = NULL; else WBScreen = theScreen;
Permit();
}
/*
* WaitForWindows()
*
* If the screen has foreign windows or icons on it
* Get a signal for this screen and clear it
* Set the Close signal and task for this screen
* While there are still icons or windows, wait for them to be closed
* (we will get a signal when they do)
* Free the signal
*/
void WaitForWindows(theScreen)
WSCREEN *theScreen;
{
ULONG mySignal;
UBYTE mySigBit;
if (theScreen && (theScreen->Window || theScreen->IconRef))
{
mySigBit = AllocSignal(-ONE);
mySignal = (mySigBit == -ONE)? DEFAULTCLOSESIGNAL: (ONE<<mySigBit);
SetSignal(mySignal,0L);
Forbid();
theScreen->CloseSignal = mySignal;
theScreen->CloseTask = FindTask(NULL);
Permit();
while (theScreen->Window || theScreen->IconRef) Wait(mySignal);
if (mySigBit != -ONE) FreeSignal(mySigBit);
}
}
/*
* StripMessages()
*
* Start with the first message in the message port
* While we are not at the tail of the list
* If the message belongs to the window we are closing
* remove it from the port and reply to it
* Go on to the next message
*/
static void StripMessages(thePort,theWindow)
struct MsgPort *thePort;
struct Window *theWindow;
{
struct Node *theMessage,*nextMessage;
theMessage = thePort->mp_MsgList.lh_Head;
while (theMessage->ln_Succ)
{
nextMessage = theMessage->ln_Succ;
if (INTUIMESSAGE->IDCMPWindow == theWindow)
{
Remove(theMessage);
ReplyMsg(theMessage);
}
theMessage = nextMessage;
}
}
/*
* CloseIconWindow()
*
* If we have a screen to work with
* And it has a backdrop window
* If the window is active, deactivate it
* If the window's UserPort is the common one
* Strip out any messages belonging to this window
* Clear the UserPort
* Clear the IDCMP flags so no messages appear while we close it
* Close the window and clear the screen's backdrop pointer
*/
void CloseIconWindow(theScreen)
WSCREEN *theScreen;
{
if (theScreen)
{
Forbid();
if (theScreen->BackDrop)
{
if (theScreen->BackDrop == ActiveWindow) SetActiveWindow(NULL);
if (theScreen->BackDrop->UserPort == wUserPort)
{
StripMessages(theScreen->BackDrop->UserPort,theScreen->BackDrop);
theScreen->BackDrop->UserPort = NULL;
ModifyIDCMP(theScreen->BackDrop,0L);
}
CloseWindow(theScreen->BackDrop);
theScreen->BackDrop = NULL;
}
Permit();
}
}
/*
* FindWindow()
*
* If we have a window to look for
* Find the screen the window is on
* If the screen was found
* Look through the window list of the screen for the given window
* Return the window or NULL
*/
WBWINDOW *FindWindow(theWindow)
struct Window *theWindow;
{
WSCREEN *theScreen;
WBWINDOW *ChkWindow = NULL;
if (theWindow)
{
Forbid();
theScreen = FindScreen(theWindow->WScreen);
if (theScreen)
{
ChkWindow = theScreen->Window;
while (ChkWindow && ChkWindow->Window != theWindow)
ChkWindow = ChkWindow->Next;
}
Permit();
}
return(ChkWindow);
}
/*
* LinkWindow()
*
* Add the window to the screen's window list
*/
void LinkWindow(theWindow,theScreen)
WBWINDOW *theWindow;
WSCREEN *theScreen;
{
Forbid();
theWindow->Screen = theScreen;
theWindow->Next = theScreen->Window; theWindow->Prev = NULL;
if (theScreen->Window) theScreen->Window->Prev = theWindow;
theScreen->Window = theWindow;
Permit();
}
/*
* UnLinkWindow()
*
* Remove the window from the screen's window list
*/
void UnLinkWindow(theWindow)
WBWINDOW *theWindow;
{
Forbid();
if (theWindow->Next) theWindow->Next->Prev = theWindow->Prev;
if (theWindow->Prev) theWindow->Prev->Next = theWindow->Next;
else theWindow->Screen->Window = theWindow->Next;
Permit();
}
/*
* NewIconWindow()
*
* If the screen is screen WBENCHSCREEN, then this is the real WB screen
* Set the backdrop window UserData to point to the screen structure
* Send the backdro pto the back (in case there are other backdrop windows)
* If the screen is only one plane deep
* Get an IntuiText from the menu list
* If the text pen is the same as the screen's block pen (ie, the text
* would be the same color as the menu background)
* Change the backdrop window's detail and block pens so that the menus
* will sho up OK
* Add the wIconify title to the backdrop window
* Show the screen title for this screen
* Give the backdrop window the common UserPort
* Set the IDCMP classes for the messages we want to receive
* Report that a new screen has openned
*/
void NewIconWindow(theScreen)
WSCREEN *theScreen;
{
struct IntuiText *theText;
extern struct MenuItem IconMenu[];
Forbid();
if ((theScreen->Screen->Flags & SCREENTYPE) == WBENCHSCREEN)
RealWB = theScreen;
Permit();
theScreen->BackDrop->UserData = (BYTE *)theScreen;
WindowToBack(theScreen->BackDrop);
if (theScreen->Screen->BitMap.Depth == 1)
{
theText = (struct IntuiText *)IconMenu[0].ItemFill;
if ((theText->FrontPen & 0x01) == theScreen->BackDrop->BlockPen)
{
theScreen->BackDrop->DetailPen = theText->FrontPen & 0x01;
theScreen->BackDrop->BlockPen = 1 - theScreen->BackDrop->DetailPen;
}
}
SetWindowTitles(theScreen->BackDrop,-1L,wIconifyTitle);
ShowTitle(theScreen->Screen,TRUE);
theScreen->BackDrop->UserPort = wUserPort;
ModifyIDCMP(theScreen->BackDrop,IDCMPFLAGS);
ReportMulti(WI_REPORTNEWSCREEN,theScreen->Screen,NULL);
}
/*
* FindIcon()
*
* If we have a window to look for
* Find the window's screen
* If it was found
* If the window is not a wIconify backdrop window
* Search through the icon list for the given icon
* Otherwise (the window is the backdrop window)
* Use the screen's icon
* Return the icon found or NULL
*/
WICONREF *FindIcon(theWindow,theScreen)
struct Window *theWindow;
WSCREEN **theScreen;
{
WICONREF *theIcon = NULL;
if (theWindow)
{
Forbid();
*theScreen = FindScreen(theWindow->WScreen);
if (*theScreen)
{
if (theWindow != (*theScreen)->BackDrop)
{
theIcon = (*theScreen)->IconRef;
while (theIcon && theIcon->Window != theWindow)
theIcon = theIcon->Next;
} else {
theIcon = &((*theScreen)->Icon);
}
}
Permit();
} else *theScreen = NULL;
return(theIcon);
}
/*
* LinkIcon()
*
* Link the Icon into the give screen's icon list
*/
void LinkIcon(theIcon,theScreen)
WICONREF *theIcon;
WSCREEN *theScreen;
{
Forbid();
theIcon->Screen = theScreen;
theIcon->Next = theScreen->IconRef; theIcon->Prev = NULL;
if (theScreen->IconRef) theScreen->IconRef->Prev = theIcon;
theScreen->IconRef = theIcon;
Permit();
}
/*
* UnLinkIcon()
*
* Remove the icon from the screen's icon list
*/
void UnLinkIcon(theIcon)
WICONREF *theIcon;
{
Forbid();
if (theIcon->Next) theIcon->Next->Prev = theIcon->Prev;
if (theIcon->Prev) theIcon->Prev->Next = theIcon->Next;
else theIcon->Screen->IconRef = theIcon->Next;
Permit();
}
/*
* RemoveAutoIcons()
*
* If a screen was specified
* Start with the first icon on the screen
* While there are more icons
* If the icon is so be removed automatically when the screen closes
* If the remove event is to be reported, do so
* If the icon has a window, restore the it
* Delete the icon from memory
* Go on to the next icon
*/
void RemoveAutoIcons(theScreen)
WSCREEN *theScreen;
{
WICONREF *theIcon,*nextIcon;
if (theScreen)
{
theIcon = theScreen->IconRef;
while (theIcon)
{
nextIcon = theIcon->Next;
if (theIcon->Icon.Flags & WI_AUTOREMOVE)
{
if (theIcon->Icon.Report & WI_REPORTAUTOREMOVE)
ReportEvent(WI_REPORTAUTOREMOVE,theIcon);
if (theIcon->Window) Restore(theIcon,TRUE);
DeleteIcon(theIcon);
}
theIcon = nextIcon;
}
}
}
/*
* ClearAllIcons()
*
* Remove the icons that can be removed automatically
* Open all icons that have windows
* While there are still icons on the screen, delete them
* (probably not a good idea, but the wIconify window is going
* to be closed, so the user won't be able to get to them anyway)
*/
static void ClearAllIcons(theScreen)
WSCREEN *theScreen;
{
RemoveAutoIcons(theScreen);
OpenAllIcons(theScreen);
while (theScreen->IconRef) DeleteIcon(theScreen->IconRef);
}
/*
* AttemptQuit()
*
* If we have not got an end singal yet
* Allocate one and clear it
* Set the current WB screen to NULL so new windows will open on the WB
* Start with the first screen
* While there are more screens
* If the screen has icons, try to clear them
* Close the wIconify backdrop window
* If the screen has no more foreign windows or icons
* Remove the screen from the list
* If the screen is one that wIconify created, close it
* Free the screen structure
* Otherwise (it has windows or icons on it, so can't be closed)
* Count the number of screens that can't be closed yet
* Go on to the next screen
* Return TRUE if all screen's are clear, otherwise return FALSE
*/
int AttemptQuit()
{
WSCREEN *theScreen,*nextScreen;
int ScreenCount = 0;
if (EndSignal == 0)
{
EndSigBit = AllocSignal(-ONE);
EndSignal = (EndSigBit == -ONE)? DEFAULTENDSIGNAL: (ONE<<EndSigBit);
SetSignal(EndSignal,0L);
}
WBScreen = NULL;
Forbid();
theScreen = FirstScreen;
while (theScreen)
{
nextScreen = theScreen->Next;
if (theScreen->IconRef) ClearAllIcons(theScreen);
CloseIconWindow(theScreen);
if (theScreen->Window == NULL && theScreen->IconRef == NULL)
{
UnLinkScreen(theScreen);
if (theScreen->Flags & WI_WSCREEN) CloseScreen(theScreen->Screen);
FREESTRUCT(wScreen,theScreen);
} else ScreenCount++;
theScreen = nextScreen;
}
Permit();
return(ScreenCount == 0);
}
/*
* FreeAllLists()
*
* While there are more screens to look at
* While there are more windows on the screen
* Free the window structure and go on to the next one
* While there are icons on the screen
* If the icon was created by wIconify
* Unlink the icon and cree it
* Free the screen structure and go on to the next one
*/
void FreeAllLists()
{
WSCREEN *theScreen,*tmpScreen;
WBWINDOW *theWindow,*tmpWindow;
WICONREF *theIcon,*tmpIcon;
theScreen = FirstScreen;
while (theScreen)
{
theWindow = theScreen->Window;
while (theWindow)
{
tmpWindow = theWindow;
theWindow = theWindow->Next;
FREESTRUCT(wbWindow,tmpWindow);
}
theIcon = theScreen->IconRef;
while (theIcon)
{
tmpIcon = theIcon;
theIcon = theIcon->Next;
if (tmpIcon->Icon.Flags & WI_SYSICON)
{
UnLinkIcon(tmpIcon);
FREESTRUCT(wIconRef,tmpIcon);
}
}
tmpScreen = theScreen;
theScreen = theScreen->Next;
FREESTRUCT(wScreen,tmpScreen);
}
}